
"use strict";

var component = function(spec, doc, env) {
  spec = spec || {};
  doc = doc || window.document;
  env = env || window.env;

  var self = {};

  self.spec = spec;

  self.localid = spec.localid || "component";
  self.document = doc;
  self.env = env;

  env = env || {};
  env.widget_prefix = env.widget_prefix || (env.extname + "-") || "";
  env.event_prefix = env.event_prefix || (env.extname + "-") || "";
  env.event_ns = env.event_ns || ("." + env.extname) || "";

  self.cleanup = [];

  self.toggleClass = function() {
    // noop by default;
  };

  self.getString = function(key) {
    // return a localized string within the extension

    if (window.strings && window.strings[key]) {
      return window.strings[key];
    }

    return [env.extname, key].join("_");
  };

  self.getAUID = function(suffix, infix) {
    infix = infix || "-";
    return [env.extname, suffix].join(infix);
  };

  self.getEventName = function(suffix,infix) {
    infix = infix || "-";
    var name = [self.auid, suffix].join(infix);
    console.log("EVENTNAME: " + name);
    return name;
  };

  self.cleanupUI = function(spec) {
    self.cleanup.forEach(function(cleaner) {
      cleaner.call(null);
    });
  };

  self.insertHandler = function(event,detail) {
    var detail = detail || event.detail || (event.originalEvent && event.originalEvent.detail);

    console.log("INSERT: " + JSON.stringify(env));

    if (detail.extname && (detail.extname !== env.extname)) {
      console.log("NOTIT");
      return true;
    }

    self.insertUI();
  };

  self.cleanupHandler = function(event,detail) {
    var detail = detail || event.detail || (event.originalEvent && event.originalEvent.detail);
    console.log("CLEANUP: " + JSON.stringify({env:env,todo:self.cleanup.length}));
    if (detail.extname && (detail.extname !== env.extname)) {
      console.log("NOTIT");
      return true;
    }

    self.cleanupUI();
  };

  self.init = function(spec) {
    self.auid = self.getAUID(self.localid || "component");

    document.addEventListener("insert-mozilla-ui", self.insertHandler, false);
    document.addEventListener("cleanup-mozilla-ui", self.cleanupHandler, false);

    self.cleanup.push(function() {
      document.removeEventListener("insert-mozilla-ui", self.insertHandler, false);
      document.removeEventListener("cleanup-mozilla-ui", self.cleanupHandler, false);
    });
  };

  return self;
};


(function() {
  "use strict";

  component.buttonComponent = function(spec, doc, env) {
    spec = spec || {};
    spec.localid = spec.localid || "button";

    var self = new component(spec, doc, env);

    self.insertUI = function(spec) {
      self.button = self.document.createElement("toolbarbutton");
      
      //jQuery(button).text('foo');
      jQuery(self.button).attr('id', self.auid);
      jQuery(self.button).attr('tooltiptext', self.getString([self.auid,"tooltip"].join(".")));
      jQuery(self.button).addClass('extension-button');
      
      jQuery("#nav-bar-customization-target").append(self.button);
      self.cleanup.push(function() { jQuery(self.button).detach(); });
      
      jQuery(self.button).on('click', function(event) {
        self.button.dispatchEvent(new CustomEvent(self.getEventName("click"), {bubbles:true,detail:{originalEvent:event}}));      
      });

      self.document.dispatchEvent(new CustomEvent('register-stylesheet', {detail:{"stylesheet": "firefox-button.css",extname: self.env.extname}}));           
    };

    self.init();

    return self;
  };

}());

"use strict";

(function() {

  component.contextitemComponent = function(spec, doc, env) {
    spec = spec || {};
    spec.localid = spec.localid || "contextitem";

    var self = new component(spec, doc, env);

    self.insertUI = function(spec) {      

      self.menuitem = self.document.createElement("menuitem");

      //jQuery(button).text('foo');
      jQuery(self.menuitem).attr('label', self.getString([self.auid,"label"].join(".")));
      jQuery(self.menuitem).attr('id', self.auid);
      jQuery(self.menuitem).addClass('extension-contextitem');

      jQuery("#contentAreaContextMenu").append(self.menuitem);
      self.cleanup.push(function() { jQuery(self.menuitem).detach(); });

      jQuery(self.menuitem).on('click', function(event) {
        var gcm = gContextMenu;
        self.document.dispatchEvent(new CustomEvent(self.getEventName('context-click'), 
                                                    {bubbles:true,detail:{originalEvent:event,context:gcm}}));            
      });

      var out = {"stylesheet": "firefox-contextitem.css",extname: self.env.extname};
      self.document.dispatchEvent(new CustomEvent('register-stylesheet', {detail:out}));           
    };

    self.init();

    return self;
  };

}());

"use strict";

(function() {

  component.pagewatcherComponent = function(spec, doc, env) {
    spec = spec || {};
    spec.localid = spec.localid || "pagewatcher";
   
    var self = new component(spec, doc, env);
   
    self.loadevents = ["DOMContentLoaded", "load"];    
    
    self.emitLoad = function(event) {
      event.target.dispatchEvent(new CustomEvent(self.getEventName("load"), {bubbles:true,detail:{originalEvent:event}}));
    };

    self.insertUI = function(spec) {
      self.appcontent = self.document.querySelector("#appcontent");
      self.loadevents.forEach(function(loadevent) {
        self.appcontent.addEventListener(loadevent, self.emitLoad, false);
        self.cleanup.push(function() { self.appcontent.removeEventListener(loadevent, self.emitLoad, false); });
      });
    };

    self.init();

    return self;
  };

    return;

  var env = window.env || {};
  env.widget_prefix = env.widget_prefix || (env.extname + "-") || "";
  env.event_prefix = env.event_prefix || (env.extname + "-") || "";
  env.event_ns = env.event_ns || ("." + env.extname) || "";

  var cleanup = [];

  var loadevents = ["DOMContentLoaded","load"].map(function(loadevent) { return loadevent + env.event_ns; });
  jQuery(document).find("#appcontent").on(loadevents.join(" "), function(event) {
    var doc = (!! event.target.ownerDocument) ? event.target.ownerDocument : event.target;
  
    document.dispatchEvent(new CustomEvent(env.event_prefix + "document-loaded", {detail:{doc:doc}}));
  });

  jQuery(document).on('cleanup-mozilla-ui' + env.event_ns, function(event) {
    cleanup.forEach(function(cleaner) {
      cleaner.call(null);
    });
    cleanup = [];

    if (env.event_ns !== '') {
      jQuery(document).find("#appcontent").off(env.event_ns);
      jQuery(document).off(env.event_ns);
    }
  });
}());

"use strict";

(function() {

  component.urlbariconComponent = function(spec, doc, env) {
    spec = spec || {};
    spec.localid = spec.localid || "urlbaricon";

    var self = new component(spec, doc, env);    

    self.insertUI = function(spec) {

      self.icon = self.document.createElement("image");
 
      jQuery(self.icon).attr('id', self.auid);
      jQuery(self.icon).attr('tooltiptext', self.getString([self.auid,"tooltip"].join(".")));
      if (self.spec && self.spec.css) {
        jQuery(self.icon).css(self.spec.css);
      }
      if (self.spec && self.spec.classes) {
        self.spec.classes.forEach(function(className) {
          jQuery(self.icon).addClass(className);
        });
      }

      jQuery('#urlbar-icons').append(self.icon);
      self.cleanup.push(function() { jQuery(self.icon).detach(); });

      jQuery(self.icon).on('click', function(event) {
        self.icon.dispatchEvent(new CustomEvent(self.getEventName('click'),
                                                {bubbles:true,detail:{originalEvent:event}}));
      });

      var out = {"stylesheet": "firefox-urlbaricon.css",extname: self.env.extname};
      self.document.dispatchEvent(new CustomEvent('register-stylesheet', {detail:out}));                 
      
    };

    self.toggleClass = function(classes, onoff) {
      jQuery(self.icon).toggleClass(classes, onoff);
    };

    self.init();

    return self;
  };

}());
